package emap;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;


import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

import java.awt.Dimension;

import java.awt.Window;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.DisplayMode;
import java.awt.event.KeyEvent;

public class Board extends JPanel implements Runnable 
{
    private Thread animator;
    private final int DELAY = 16;
    
    private long runs;
    private Tileset tileset;
    private Map currentMap;
    private ObjectDrawnList objdlist;
    private ObjectGfxSheet objgfx;
    private ObjectDrawn person1;
    private ObjectDrawn person2;
    private InputManager inputman;
    private ViewportManager viewman;
    private Viewport myview1;
    private Viewport myview2;
    private final int viewscrollspeed=5;
    private Color bgcol;
    private boolean keepgoing;
    private boolean drawNow;
    private boolean runNow;
    private boolean paused;
    private Coord mapDim;
    private Rect mapRect;
    private ArrayList<Controller> myControls;
    private ArrayList<BasicPerson> myPeeps;
    
    public Board() //called when initialized.
    {
    	bgcol=new Color(100,75,100);
        setBackground(bgcol);
        setDoubleBuffered(true);
        
        tileset = new Tileset("FarmVillage");
        currentMap = new Map("TestMap");
        objgfx=new ObjectGfxSheet("Faye");
        objdlist=new ObjectDrawnList(currentMap.getLevels());
        person1=new ObjectDrawn(47,102,1,0,2,1);
        person2=new ObjectDrawn(79,102,1,0,1,3);
        //objdlist.AddObj(person1);
        //objdlist.AddObj(person2);
        setFocusable(true);
        inputman=new InputManager();
        addKeyListener(inputman);
        addMouseListener(inputman);
        addMouseMotionListener(inputman);
		//Set up the Viewport(s)! Woote!
		mapDim=new Coord(currentMap.getXLength()*32,currentMap.getYLength()*32);
		viewman=new ViewportManager();
		myview1=new Viewport(0,0,320,240,mapDim);
		myview2=new Viewport(320,0,320,240,mapDim);
		viewman.addView(myview1);
		viewman.addView(myview2);
		viewman.addView(new Viewport(0,240,320,240,mapDim));
		viewman.addView(new Viewport(320,240,320,240,mapDim));
		myControls=new ArrayList<Controller>();
		myPeeps=new ArrayList<BasicPerson>();
		BasicPerson newbp=new BasicPerson();
		myPeeps.add(newbp);
		HumanController hc=new HumanController(newbp);
		ArrayList<InputKey> newcon=new ArrayList<InputKey>(); //up left down right
		newcon.add(inputman.registerKey(KeyEvent.VK_W,"W"));
		newcon.add(inputman.registerKey(KeyEvent.VK_A,"A"));
		newcon.add(inputman.registerKey(KeyEvent.VK_S,"S"));
		newcon.add(inputman.registerKey(KeyEvent.VK_D,"D"));
		hc.setControls(newcon);
		myControls.add(hc);
		newbp=new BasicPerson();
		hc=new HumanController(newbp);
		newcon=new ArrayList<InputKey>();
		newcon.add(inputman.registerKey(KeyEvent.VK_UP,"upkey"));
		newcon.add(inputman.registerKey(KeyEvent.VK_LEFT,"downkey"));
		newcon.add(inputman.registerKey(KeyEvent.VK_DOWN,"leftkey"));
		newcon.add(inputman.registerKey(KeyEvent.VK_RIGHT,"rightkey"));
		hc.setControls(newcon);
		myControls.add(hc);
		myPeeps.add(newbp);
        objdlist.AddObj(myPeeps.get(0).getOD());
        objdlist.AddObj(myPeeps.get(1).getOD());
        
        
        System.out.println(currentMap.toString());
        runNow=true;
        drawNow=false;
        paused=false;
        //addNotify();
        mapRect=new Rect(0,0,mapDim.X,mapDim.Y);
    }
    public void addNotify() 
    {
        super.addNotify();
        animator = new Thread(this);
        animator.start();
    }
    
    public void paint(Graphics g) //called about 60 times every second.
    {
    	if(drawNow==false) return;
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        viewman.setDrawTo(g2d);
        int a;
        Dimension mydim=getSize();
        int center_x=mydim.width/2;
        int center_y=mydim.height/2;
        int myYLength=currentMap.getYLength();
        int myXLength=currentMap.getXLength();
        int levels=currentMap.getLevels();
        GridSquare cursqr=new GridSquare();
        Tile curtile=new Tile();
        ObjectDrawn curod=new ObjectDrawn();
        int curimg;
        int numobjs;
        for(int lev=0;lev<levels;lev++)
        {
        	for(int y=0;y<myYLength;y++)
        	{
        		for(int x=0; x<myXLength;x++)
        		{
        			cursqr=currentMap.getSquare(x,y);
        			int reallevels=cursqr.getNumTiles();
        			for(int tlev=0;tlev<reallevels;tlev++)
        			{
        				curtile=cursqr.get(tlev);
        				curimg=curtile.getImagePointer();
        				if(curtile.getLevel()==lev)
        				viewman.drawImage(tileset.getTileImage(curimg),curtile.myTileSize*x,curtile.myTileSize*y);
        			}
        		}
        	}
        	for(numobjs=objdlist.NumObjsInLevel(lev);numobjs>0;numobjs--)
        	{
        		curod=objdlist.GetObj(lev,numobjs-1);
        		curimg=curod.getImgPtr();
        		viewman.drawImage(objgfx.rawgetObjectGfx(curimg),curod.getX(),curod.getY());
        	}
        }
        //g2d.drawImage(objgfx.rawgetObjectGfx(0),inputman.mouse_pos.X,inputman.mouse_pos.Y,null);
        
        //person1.animate();
        //person2.animate();
        objdlist.resetobjectlist();
        //objdlist.AddObj(person1);
        //objdlist.AddObj(person2);
        for(Controllable curPeep : myPeeps)
        {
        	curPeep.myAction();
        	objdlist.AddObj(curPeep.getOD());
        }
        
        g.setColor(Color.BLACK);
        g.drawLine(320,0,320,480);
        g.drawLine(0,240,640,240);
        
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
        drawNow=false;
        if(paused==false) runNow=true;
    }
    public void cycle()
    {
    	if(runNow==false) return;
    	//Pause or Unpause here
    	if(paused==true) return;
    	runs++;
    	/*
    	if(inputman.key_up) {person1.moveBy(0,-viewscrollspeed,mapDim);person1.reface(3);}
    	if(inputman.key_down) {person1.moveBy(0,viewscrollspeed,mapDim);person1.reface(0);}
    	if(inputman.key_left) {person1.moveBy(-viewscrollspeed,0,mapDim);person1.reface(1);}
    	if(inputman.key_right) {person1.moveBy(viewscrollspeed,0,mapDim);person1.reface(2);}
    	if(inputman.key_w) {person2.moveBy(0,-viewscrollspeed,mapDim);person2.reface(3);}
    	if(inputman.key_s) {person2.moveBy(0,viewscrollspeed,mapDim);person2.reface(0);}
    	if(inputman.key_a) {person2.moveBy(-viewscrollspeed,0,mapDim);person2.reface(1);}
    	if(inputman.key_d) {person2.moveBy(viewscrollspeed,0,mapDim);person2.reface(2);}
    	if(inputman.key_space) keepgoing=false;
    	*/
    	if(inputman.key_i) System.out.println(myPeeps.get(0).getPos());
    	if(inputman.key_j) System.out.println(myPeeps.get(1).getPos());
    	myPeeps.get(0).moveBy(0,0,mapDim);
    	myPeeps.get(1).moveBy(0,0,mapDim);
    	myview1.centerOn(myPeeps.get(0).getPos().X,myPeeps.get(0).getPos().Y);
    	myview2.centerOn(myPeeps.get(1).getPos().X,myPeeps.get(1).getPos().Y);
    	for(Controller curCon : myControls)
    	curCon.doControls();
    	runNow=false;
    	drawNow=true;
    }
    public void run() { //I shouldn't need to mess with this. 

        long beforeTime, timeDiff, sleep;

        beforeTime = System.currentTimeMillis();
        keepgoing=true;

        while (keepgoing) {

            cycle();
            repaint();

            timeDiff = System.currentTimeMillis() - beforeTime;
            sleep = DELAY - timeDiff;

            if (sleep < 0)
                sleep = 2;
            try {
                Thread.sleep(sleep);
            } catch (InterruptedException e) {
                System.out.println("interrupted");
            }

            beforeTime = System.currentTimeMillis();
        }
        System.exit(0);
    }
}